//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.Generic;

namespace OpenLS.Vml.Parsing
{
    /// <summary>
    /// This stack maintains a high water mark for allocated objects so the client
    /// can reuse the objects in the stack to reduce memory allocations, this is
    /// used to maintain current state of the parser for element stack, and attributes
    /// in each element.
    /// </summary>
    internal class HWStack<T>
    {
        private readonly int _growth;
        private int _count;
        private T[] _items;

        public HWStack(int growth)
        {
            _growth = growth;
        }
        public IEnumerable<T> GetItems()
        {
            int count = Count;
            for (int i = count - 1; i >= 0; i--)
                yield return this[i];
        }

        public int Count
        {
            get { return _count; }
            set { _count = value; }
        }


        private int Size { get; set; }

        // returns the item at the requested index or null if index is out of bounds
        public T this[int i]
        {
            get { return (i >= 0 && i < Size) ? _items[i] : default(T); }
            set { _items[i] = value; }
        }

        public T Pop()
        {
            _count--;
            if (_count > 0)
            {
                return _items[_count - 1];
            }
            return default(T);
        }

        // This method tries to reuse a slot, if it returns null then
        // the user has to call the other Push method.
        public T Push()
        {
            if (_count == Size)
            {
                int newsize = Size + _growth;
                var newarray = new T[newsize];
                if (_items != null)
                    Array.Copy(_items, newarray, Size);
                Size = newsize;
                _items = newarray;
            }
            return _items[_count++];
        }
    }
}